package cn.mw.cmdb.util;

import cn.mw.cmdb.entity.graph.EdgeParam;
import cn.mw.cmdb.entity.graph.NodeParam;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.driver.Record;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ModelAssetUtils {
    private static int DEFAULT_LEVEL = 0;
    public static String DEFAULT_INSTANCE_LABEL = "InstanceLabel";
    public static String MODEL_SPACE = "ModelAsset";
    public static String MODEL_RELATIONSHIP = "RelateModel";
    public static final String INSTANCE_COMMON_VIEW = "InstanceCommonView";
    public static final String VIRTUAL_SPACE = "Virtual";
    public static final String CITRIX_SPACE = "Citrix";
    public static final String COMMON_SPACE = "mwModelId";
    public static final String INSTANCE_CUSTOM_VIEW = "InstanceCustomView";

    private static final String BatcheMergeLine = "unwind $lines AS line match (a:#space {id:line.start.id}), (b:#space {id:line.end.id}) with a,b merge (a)-[:#space]->(b)";
    private static final String BatchSetNodeLabel = "unwind $nodes as node merge (n:#default_space:#space {id:node.id})";
    private static final String FindLevel = "MATCH p=((a:#space {id:$id})-[:#relationship*]-()) RETURN max(length(p)) as level;";
    private static final String FindTreeEdge = "MATCH (a:#space {id:'#id'}) CALL apoc.path.spanningTree(a,{labelFilter:'#space' ,minLevel:1 ,maxLevel:#level})  YIELD path RETURN nodes(path) as p";
    private static final String DeleteInstanceNode_Merge = "MERGE (:#space {id:'#id'})";
    private static final String DeleteInstanceNode_Connect = "MATCH (a:#defaultspace {id:'#startId'}) ,(b:#defaultspace {id:'#endId'}) WITH a,b MERGE (a)-[:#space]->(b);";
    private static final String DeleteInstanceNode_Label = "MATCH (n:#default_space {id:'#id'}) set n#spaces;";
    private static final String DeleteInstanceNode = "MATCH (n:#defaultspace) WHERE n.id IN [#ids] detach delete n;";

    public static int findModelRelateLevel(Session session, String modelId) {
        String query = FindLevel.replaceAll("#space", MODEL_SPACE)
                .replaceAll("#id", modelId.toString()).replaceAll("#relationship", MODEL_RELATIONSHIP);
        Map criteria = new HashMap();
        criteria.put("id", modelId);
        int ret = doLevelQuery(session, query, criteria);
        return ret;
    }

    private static int doLevelQuery(Session session, String query, Map criteria) {
        int ret = 0;
        Result result = session.run(query, criteria);
        while (result.hasNext()) {
            Record record=result.next();
            Long retLong = record.get("level").asLong();
            if (null == retLong) {
                ret = DEFAULT_LEVEL;
            } else {
                ret = retLong.intValue();
            }

        }
        return ret;
    }

    public static List<EdgeParam> findEdgeBySpace(Session session, NodeParam start, String space, int maxLevel) {
        return doFindEdgeBySpace(session, start, space, maxLevel, "RELATIONSHIP_PATH");
    }

    private static List<EdgeParam> doFindEdgeBySpace(Session session, NodeParam start, String space, int maxLevel
            , String strategy) {

        List<EdgeParam> ret = new ArrayList<>();
        String pathKey = "p";
        String query = FindTreeEdge.replaceAll("#space", space)
                .replaceAll("#id", start.getId()).replaceAll("#level", String.valueOf(maxLevel))
                .replaceAll("#strategy", strategy);
        Map criteria = new HashMap();
        criteria.put("space", space);
        criteria.put("start", start.getId());
        Result result = session.run(query, criteria);
        while (result.hasNext()) {
            Record record =result.next();
            // Todo 实现逻辑
//            List<NodeModel> nodeModels = record.get(pathKey).asList();
//            for (int i = 0; i < nodeModels.size() - 1; i++) {
//                String startId = nodeModels.get(i)
//                        .getPropertyList().get(0).toString().replaceAll("id :", "").trim();
//
//                String endId = nodeModels
//                        .get(i + 1).getPropertyList().get(0).toString().replaceAll("id :", "").trim();
//                EdgeParam edgeParam = new EdgeParam(startId, endId);
//                if (!ret.contains(edgeParam)) {
//                    ret.add(edgeParam);
//                }
//            }
        }

        return ret;
    }
}
